#pragma once
#include "Line.h"
#include "Triangle.h"
#include "Material.h"
#include "ColorValue.h"
#include "vector3f.h"
#include "Scene.h"
#include "GeometricTools.h"

class Tracer
{
public:
	const static float RayThreshold;
	const static float TransparenceThreshold;
	const static float ReflectionThreshold;
    int m_nTraced;
    int m_nTracedReflect;
    int m_nTracedRefract;

private:
	Scene *m_pScene;

private:
    
    float AmbientColorContributionRate(Material& material)
    {
        return material.GetAlpha();
    }

// 	float DiffusionColorContributionRate(Material& material)
// 	{
// 		return material.GetAlpha() * (1 - material.GetReflectivity());
// 	}
	float DiffusionColorContributionRate(Material& material, float alpha)
	{
		return alpha * (1 - material.GetReflectivity());
	}

// 	float ReflectionColorContributionRate(Material& material)
// 	{
// 		return material.GetAlpha() * material.GetReflectivity();
// 	}
	float ReflectionColorContributionRate(Material& material, float alpha)
	{
		return alpha * material.GetReflectivity();
	}

// 	float TransparenceContributionRate(Material& material)
// 	{
// 		return (1 - material.GetAlpha()) * (1 - material.GetReflectivity());
// 	}
	float TransparenceContributionRate(Material& material, float alpha)
	{
		return (1 - alpha) * (1 - material.GetReflectivity());
	}

// 	float RefractionContributionRate(Material& material)
// 	{
// 		return (1 - material.GetAlpha()) * material.GetReflectivity();
// 	}
	float RefractionContributionRate(Material& material, float alpha)
	{
		return (1 - alpha) * material.GetReflectivity();
	}

	ColorValue CalculateAllDiffuseAndSpecularColor(float weight, Line& incidentRay,
		Triangle& triangle, Vector3f& intersectionPoint, Vector3f& surfaceNormal, Material& material, float alpha);

	ColorValue CalculateSpecularColor(Light* light, Line& incidentRay,
		Triangle& triangle, Vector3f& intersectionPoint, Vector3f& surfaceNormal,
		Material& material, Vector2& textureCoordinate);

	ColorValue CalculateBackSpecularColor(Light* light, Line& incidentRay,
		Triangle& triangle, Vector3f& intersectionPoint, Vector3f& surfaceNormal,
		Material& material, Vector2& textureCoordinate);

	ColorValue CalculateDiffuseColor(Light* light, Line& incidentRay,
		Triangle& triangle, Vector3f& intersectionPoint, Vector3f& surfaceNormal,
		Material& material, Vector2& textureCoordinate);

	ColorValue CalculateTransparentDiffuseColor(Light* light, Line& incidentRay,
		Triangle& triangle, Vector3f& intersectionPoint, Vector3f& surfaceNormal,
		Material& material, Vector2& textureCoordinate);


	void DoTrace(Line& incidentRay, unsigned int depth, float weight, Material& currentMaterial,
		ColorValue* outColor);

	float CalculateFresnelAlpha(Material &material, Line &incidentRay, Vector3f& surfaceNormal);


public:
	/// @incidentRay
	///		The ray to trace.
	/// @depth
	///		The depth of recursion.
	/// @currentMaterial
	///		The material of incident ray comes from.
	/// @return
	///		The color value of incidentRay.
	ColorValue Trace(Line& incidentRay, unsigned int depth, Material& currentMaterial);

	Tracer();

    void Init(Scene* pScene);

	virtual ~Tracer(void);

};

